/**
 * @file shell.c
 * @author zhaitao (zhaitao.as@outlook.com)
 * @brief export shell command
 * @version 0.1
 * @date 2020-07-10
 * 
 * @copyright Copyright (c) 2020
 * 
 */
#include "shell_export.h"
#include "main.h"
#include "util.h"

#include "shell_uid.h"
#include "shell_t10.h"
#include "shell_lua.h"
#include "shell_ssd2828.h"

ntshell_t ntshell;
extern UART_HandleTypeDef huart1;
extern void RA8876_GraphicDrawingMode(void);
extern void fillColor(uint32_t color);//TODO

int uart_putc(char c)
{
	HAL_UART_Transmit(&huart1, (uint8_t *)&c, 1, 0xffff);
	return c;
}

int uart_getc(void)
{
	int rcv;
	HAL_UART_Receive(&huart1, (uint8_t *)&rcv, 1, 0xffff);
	return rcv;
}

int uart_puts(const char *s)
{
	int cnt = 0;
	char *p = (char *)s;
	while (*p) {
		uart_putc(*p);
		p++;
		cnt++;
	}
	return cnt;
}

#define UNUSED_VARIABLE(N)                                                     \
	do {                                                                   \
		(void)(N);                                                     \
	} while (0)

int func_read(char *buf, int cnt, void *extobj)
{
	int i;
	UNUSED_VARIABLE(extobj);
	for (i = 0; i < cnt; i++) {
		buf[i] = uart_getc();
	}
	return cnt;
}

int func_write(const char *buf, int cnt, void *extobj)
{
	int i;
	UNUSED_VARIABLE(extobj);
	for (i = 0; i < cnt; i++) {
		uart_putc(buf[i]);
	}
	return cnt;
}

typedef int (*USRCMDFUNC)(int argc, char **argv);

typedef struct {
	char *cmd;
	char *desc;
	USRCMDFUNC func;
} cmd_table_t;

static int ntshell_help(int argc, char **argv);
static int ntshell_info(int argc, char **argv);

static const cmd_table_t cmdlist[] = {
    {"uid", "This is a description text string for info command.", ntshell_getUID},
    {"help", "This is a description text string for help command.", ntshell_help},
    {"info", "This is a description text string for info command.",  ntshell_info},
    {"lua", "This is a description text string for info command.", lua_shell},
    {"t10", "This is a description text string for info command.", ntshell_test10},
    {"ssd2828", "ssd2828 MIPI to RGB converter functions", ntshell_ssd2828},
};

static int ntshell_help(int argc, char **argv)
{
	const cmd_table_t *p = &cmdlist[0];
	for (int i = 1; i < sizeof(cmdlist) / sizeof(cmdlist[0]); i++) {
		uart_puts(cmdlist[i].cmd);
		uart_puts("\t:");
		uart_puts(cmdlist[i].desc);
		uart_puts("\r\n");
		p++;
	}
	return 0;
}

static int ntshell_info(int argc, char **argv)
{
	if (argc != 2) {
		uart_puts("info sys\r\n");
		uart_puts("info ver\r\n");
		return 0;
	}
	if (ntlibc_strcmp(argv[1], "sys") == 0) {
		uart_puts("NXP LPC824 Monitor\r\n");
		return 0;
	}
	if (ntlibc_strcmp(argv[1], "ver") == 0) {
		uart_puts("Version 0.0.0\r\n");
		return 0;
	}
	uart_puts("Unknown sub command found\r\n");
	return -1;
}


static int usrcmd_ntopt_callback(int argc, char **argv, void *extobj)
{
	if (argc == 0) {
		return 0;
	}
	const cmd_table_t *p = &cmdlist[0];
	for (int i = 0; i < sizeof(cmdlist) / sizeof(cmdlist[0]); i++) {
		if (ntlibc_strcmp((const char *)argv[0], p->cmd) == 0) {
			return p->func(argc, argv);
		}
		p++;
	}
	uart_puts("Unknown command found.\r\n");
	return 0;
}

int usrcmd_execute(const char *text)
{
	return ntopt_parse(text, usrcmd_ntopt_callback, 0);
}

int func_callback(const char *text, void *extobj)
{
	usrcmd_execute(text);
	return 0;
}
